現行的主流概念中,我們很常聽到一個論述:每個測試中只能含有一個斷言 (Assert)。這個準則看似過於嚴厲,但好處也是顯而易見,讀者可以很快速地了解測試內容。依循這個指導方針,我們也會很自然地如昨天所述,建立公用函式來支援測試需求。
然而,在某些時候為了符合「一個測試,一個斷言」的需求,將測試內容重構似乎會顯得有些小題大作,因此作者仍偏好保持多個斷言的模式。也就是說,作者認為單一斷言原則是個不錯的指導方針,他會使測試裡的斷言數量盡可能的少,但也並不害怕使用多個斷言。
也許更好的準則是,在每個測試函式裡只測試一個概念。
我們並不希望擁有一個冗長的單元測試,但通常造成問題的並不是測試中有多個斷言,而是源於測試中有多個概念。在單一測試中有太多不同的概念,除了容易導致測試者錯漏重要的項目,也會讓讀者感到混亂與困惑。所以我們應該最小化每個概念中的斷言數量,而每個測試函式中只能測試一個概念。
F.I.R.S.T,這五個字母組成了一個整潔測試所需具備的要素:
Fast(快速): 單元測試應該要能夠快速的運行,若每次的測試都要等待漫長的時間,我們就會越來越不愛進行測試,最後,程式會開始腐敗。
Independent(獨立): 測試程式必須要可以獨立運行,彼此之間不應該彼此依賴,前一個測試不可為下一個測試設定條件。一旦測試程式彼此產生因果關係,我們就很難判斷究竟錯誤是來自於函式本身抑或是其他原因,進而造成除錯上的困難。同樣地,當測試成功時我們也無法確定是真的驗證通過,還是有其他因素導致成功。
Repeatable(可重複性): 測試程式應該要能在任何環境中被重複執行。如果單元測試無法保證在任何環境中都能正常運行,那麼我們就永遠會有「為什麼測試會失敗」的藉口,而將關注點偏離了測試主體。
Self-Validating(自我驗證): 測試程式應該輸出布林值。不管結果是成功或失敗,我們不應該去查看紀錄檔才能分辨結果。當我們需要手動查看及分辨時,測試就會變成一種主觀的看法,並且可能會需要大量的檢查時間。當然,現今主流的測試套件基本上都支援這項功能,所以我們已不需為此特別費心。
Timely(及時): 單元測試應在產品程式前不久撰寫。也就是說,我們在撰寫單元測試前不應該先寫出產品程式的內容,其原因在於當我們已先完成產品程式時,我們可能會發現它太難被測試,於是我們就放棄為它做測試。
我們花了三天在聊關於單元測試的內容,但事實上在整潔測試的領域中,只能算是接觸了一些皮毛,畢竟這是一個極廣且深的議題。對我來說,單元測試一直僅停留在簡單嘗試過的階段,所以也藉此機會費了些功夫去了解、學習這個議題,希望也能對大家有所幫助。那麼,今天我們將正式結束這個話題,繼續向下一章推進。